package com.wangshupo.app.geekpark.service.impl;

import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.wangshupo.app.geekpark.model.News;
import com.wangshupo.app.geekpark.param.NewsQueryParam;
import com.wangshupo.app.geekpark.service.NewsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.function.LongSupplier;

/**
 * 新闻服务实现
 */
@Service
public class NewsServiceimpl implements NewsService {
    private static final Logger LOG = LoggerFactory.getLogger(NewsServiceimpl.class);

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public News addNews(News news) {
        // 作为服务，要对入参进行判断，不能假设被调用时，传入的一定是真正的对象
        if (news == null) {
            LOG.error("input news data is null.");
            return null;
        }

        if (news.getGmtCreated() == null) {
            news.setGmtCreated(LocalDateTime.now());
        }
        if (news.getGmtModified() == null) {
            news.setGmtModified(LocalDateTime.now());
        }

        return mongoTemplate.insert(news);
    }

    @Override
    public News getNewsById(String newsId) {
        // 输入的主键 id 必须有文本，不能为空或全空格
        if (!StringUtils.hasText(newsId)) {
            LOG.error("input newsId is blank.");
            return null;
        }

        News news = mongoTemplate.findById(newsId, News.class);
        return news;
    }


    /**
     * 查询所有数据
     * @param param
     * @return
     */
    @Override
    public Page<News> list(NewsQueryParam param) {
        // 作为服务，要对入参进行判断，不能假设被调用时，入参一定正确
        if (param == null) {
            LOG.error("input query param data is not correct.");
            return null;
        }

        // 总条件
        Criteria criteria = new Criteria();

        // 条件对象构建查询对象
        Query query = new Query(criteria);
        // 总数
        long count = mongoTemplate.count(query, News.class);

        // 构建分页对象。注意此对象页码号是从 0 开始计数的。
        Pageable pageable = PageRequest.of(param.getPageNum() - 1, param.getPageSize());
        query.with(pageable);

        // 查询结果
        List<News> songs = mongoTemplate.find(query, News.class);
        // 构建分页器
        Page<News> pageResult = PageableExecutionUtils.getPage(songs, pageable, new LongSupplier() {
            @Override
            public long getAsLong() {
                return count;
            }
        });

        return pageResult;
    }

    @Override
    public boolean modify(News news) {
        // 作为服务，要对入参进行判断，不能假设被调用时，入参一定正确
        if (news == null || !StringUtils.hasText(news.getId())) {
            LOG.error("input news data is not correct.");
            return false;
        }

        // 主键不能修改，作为查询条件
        Query query = new Query(Criteria.where("id").is(news.getId()));

        Update updateData = new Update();
        // 每次修改都更新 gmtModified 为当前时间
        updateData.set("gmtModified", LocalDateTime.now());
        // 值为 null 表示不修改。值为长度为 0 的字符串 "" 表示清空此字段
        if (news.getTitle() != null) {
            updateData.set("title", news.getTitle());
        }

        if (news.getDesc() != null) {
            updateData.set("desc", news.getDesc());
        }

        if (news.getCover() != null) {
            updateData.set("cover", news.getCover());
        }

        if (news.getAuthorIds() != null) {
            updateData.set("authorIds", news.getAuthorIds());
        }

        // 把一条符合条件的记录，修改其字段
        UpdateResult result = mongoTemplate.updateFirst(query, updateData, News.class);
        return result != null && result.getModifiedCount() > 0;
    }

    @Override
    public boolean delete(String newsId) {
        // 输入的主键 id 必须有文本，不能为空或全空格
        if (!StringUtils.hasText(newsId)) {
            LOG.error("input newsId is blank.");
            return false;
        }

        News news = new News();
        news.setId(newsId);

        DeleteResult result = mongoTemplate.remove(news);
        return result != null && result.getDeletedCount() > 0;
    }
}
